package wsp.dailymarket;

import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.Blob;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.imageio.stream.ImageInputStream;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;

/**
 * Servlet for serving images from the database
 * @author Matt
 */
public class DealImage extends HttpServlet {

	private static final int DEFAULT_SIZE = -1;
	private static final String PNG_EXT = ".png";
	@Resource(name = "jdbc/dmderby")
	private DataSource ds;

	private void sendInvalidImage(HttpServletResponse resp, int size) {
		// Get the absolute path of the image
		ServletContext sc = getServletContext();
		String filename = sc.getRealPath("resources/images/no_image.png");

		try {
			// Dump image from file
			OutputStream os = null;
			FileInputStream fis = null;
			ImageInputStream iis = null;
			try {
				fis = new FileInputStream(filename);
				BufferedImage img = ImageIO.read(fis);
				BufferedImage imgOut = img;
				if (size > 0) {
					int srcWidth = img.getWidth();
					int srcHeight = img.getHeight();
					float aspect = (float) srcWidth / (float) srcHeight;
					int dstWidth = 0;
					int dstHeight = 0;
					if (srcWidth > srcHeight) {
						dstWidth = size;
						dstHeight = Math.round(size / aspect);
					} else {
						dstHeight = size;
						dstWidth = Math.round(size * aspect);
					}
					imgOut = new BufferedImage(dstWidth, dstHeight, BufferedImage.TYPE_INT_ARGB);
					Graphics2D g = (Graphics2D) imgOut.getGraphics();
					g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
					g.drawImage(img, 0, 0, dstWidth, dstHeight, null);
					g.dispose();
				}
				resp.setContentType("image/png");
				os = resp.getOutputStream();
				ImageIO.write(imgOut, "png", os);
			} finally {
				if (os != null) {
					os.close();
				}
				if (fis != null) {
					fis.close();
				}
				if (iis != null) {
					iis.close();
				}
			}
		} catch (IOException ex) {
			resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
			sc.log("IOException: ", ex);
		}
	}

	/**
	 * Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods.
	 * @param request servlet request
	 * @param response servlet response
	 * @throws ServletException if a servlet-specific error occurs
	 * @throws IOException if an I/O error occurs
	 */
	protected void processRequest(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		String requestUrl = request.getPathInfo();
		if (requestUrl == null) {
			// Send invalid image
			this.sendInvalidImage(response, DEFAULT_SIZE);
		} else {
			// Parse path info into parameters
			if (requestUrl.startsWith("/")) {
				String[] parts = requestUrl.split("/");
				int id = -1;
				int size = DEFAULT_SIZE;
				for (int i = 0; i
						< parts.length; i++) {
					if (id < 0 && parts[i].toLowerCase().endsWith(PNG_EXT)) {
						try {
							id = Integer.parseInt(parts[i].substring(0, parts[i].indexOf(PNG_EXT)));
						} catch (NumberFormatException ex) {
						} // Oh well, ignore
					} else if (size < 0) {
						try {
							size = Integer.parseInt(parts[i]);
						} catch (NumberFormatException ex) {
						} // Oh well, ignore
					}
				}
				if (id < 1) {
					this.sendInvalidImage(response, size);
				}
				Connection conn = null;
				try {
					try {
						conn = ds.getConnection();
						Statement stmt = conn.createStatement();
						ResultSet rs = stmt.executeQuery("SELECT * FROM APP.DEAL_IMAGES WHERE id = " + id);
						if (rs.next()) {
							// Dump image from ResultSet
							OutputStream os = null;
							InputStream is = null;
							ImageInputStream iis = null;
							try {
								Blob iData = rs.getBlob("image_data");
								is = iData.getBinaryStream();
								BufferedImage img = ImageIO.read(is);
								BufferedImage imgOut = img;
								if (size > 0) {
									int srcWidth = img.getWidth();
									int srcHeight = img.getHeight();
									float aspect = (float) srcWidth / (float) srcHeight;
									int dstWidth = 0;
									int dstHeight = 0;
									if (srcWidth > srcHeight) {
										dstWidth = size;
										dstHeight = Math.round(size / aspect);
									} else {
										dstHeight = size;
										dstWidth = Math.round(size * aspect);
									}
									imgOut = new BufferedImage(dstWidth, dstHeight, BufferedImage.TYPE_INT_ARGB);
									Graphics2D g = (Graphics2D) imgOut.getGraphics();
									g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
									g.drawImage(img, 0, 0, dstWidth, dstHeight, null);
									g.dispose();
								}
								response.setContentType("image/png");
								os = response.getOutputStream();
								ImageIO.write(imgOut, "png", os);
							} finally {
								if (os != null) {
									os.close();
								}
								if (is != null) {
									is.close();
								}
								if (iis != null) {
									iis.close();
								}
							}
						} else {
							// Image not found
							this.sendInvalidImage(response, size);
						}
					} finally {
						if (conn != null) {
							conn.close();
						}
					}
				} catch (SQLException ex) {
					getServletContext().log("SQLException: ", ex);
					response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
				}
			} else {
				// Send invalid image (should not happen)
				this.sendInvalidImage(response, 200);
			}
		}
	}

	// <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
	/**
	 * Handles the HTTP <code>GET</code> method.
	 * @param request servlet request
	 * @param response servlet response
	 * @throws ServletException if a servlet-specific error occurs
	 * @throws IOException if an I/O error occurs
	 */
	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		processRequest(request, response);




	}

	/**
	 * Handles the HTTP <code>POST</code> method.
	 * @param request servlet request
	 * @param response servlet response
	 * @throws ServletException if a servlet-specific error occurs
	 * @throws IOException if an I/O error occurs
	 */
	@Override
	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		processRequest(request, response);




	}

	/**
	 * Returns a short description of the servlet.
	 * @return a String containing servlet description
	 */
	@Override
	public String getServletInfo() {
		return "Short description";


	}// </editor-fold>
}
